<template>
  <div class="graph-container">
    <div class="graph-tools">
      <el-button-group>
        <el-button size="small" @click="toggleEditMode">
          {{ isEditMode ? '退出编辑' : '进入编辑' }}
        </el-button>
        <!-- <el-button size="small" type="primary" @click="addNode" :disabled="!isEditMode">
          添加节点
        </el-button>
        <el-button size="small" type="danger" @click="deleteSelectedNode" :disabled="!isEditMode || !selectedNode">
          删除节点
        </el-button> -->
        <el-button size="small" type="success" @click="saveGraph">
          保存图谱
        </el-button>
        <!-- <el-button size="small" type="warning" @click="showRelationDialog = true">
          导入关系数据
        </el-button> -->
      </el-button-group>
      <div class="tool-tips" v-if="isEditMode">
        <el-tag size="small" type="info">拖拽节点调整位置</el-tag>
        <el-tag size="small" type="info">点击节点编辑名称</el-tag>
        <el-tag size="small" type="info">拖动可创建新连线</el-tag>
        <el-tag size="small" type="info">右键节点显示菜单</el-tag>
      </div>
    </div>
    <div class="graph-content" @contextmenu.prevent>
      <div id="graph" style="width: 100%; height: 500px;"></div>
      
      <!-- 右键菜单 -->
      <div class="context-menu" v-show="showContextMenu" :style="contextMenuStyle">
        <ul>
          <li @click="addNodeFromMenu"><i class="el-icon-plus"></i> 添加子节点</li>
          <li @click="deleteSelectedNode"><i class="el-icon-delete"></i> 删除当前节点</li>
          <li @click="editNodeFromMenu"><i class="el-icon-edit"></i> 编辑节点</li>
        </ul>
      </div>
    </div>
    
    <!-- 关系数据导入对话框 -->
    <el-dialog title="导入关系数据" :visible.sync="showRelationDialog" width="650px">
      <el-form>
        <el-form-item label="数据格式">
          <div class="format-tip">
            格式：节点A-ID,节点B-ID,关系类型；每行一条或分号分隔<br>
            例如：上游-2,工业母机-1,part-of;
          </div>
        </el-form-item>
        <el-form-item>
          <el-input
            type="textarea"
            :rows="10"
            placeholder="请输入关系型数据"
            v-model="relationData">
          </el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="showRelationDialog = false">取消</el-button>
        <el-button type="primary" @click="handleImportRelation">导入</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import * as echarts from 'echarts'
// 引入JSON数据文件 - 请根据您的实际路径调整
import industryChainData from '@/assets/data/industry-chain-data.json'

export default {
  name: 'IndustryChainGraph',
  data() {
    return {
      graph: null,
      isEditMode: false,
      selectedNode: null,
      showContextMenu: false,
      contextMenuStyle: {
        left: '0px',
        top: '0px'
      },
      graphData: {
        nodes: [],
        links: []
      },
      isLoading: false,
      showRelationDialog: false,
      relationData: ''
    }
  },
  methods: {
    // 从JSON文件加载数据
    loadLocalData() {
      this.isLoading = true
      // 直接使用导入的JSON数据
      this.processGraphData(industryChainData)
      this.initGraph()
      this.isLoading = false
    },

    // 解析关系数据并转换为图谱格式
    parseRelationData(relationText) {
      this.isLoading = true
      
      // 解析行数据
      const lines = relationText.split(/[\n;]+/).filter(line => line.trim());
      const relationData = {
        nodes: {},
        links: []
      };
      
      // 解析每行数据并提取节点和关系
      lines.forEach(line => {
        const parts = line.split(',').map(p => p.trim());
        if (parts.length >= 3) {
          const [nodeA, nodeB, relation] = parts;
          
          // 解析节点A信息
          const [nameA, idA] = nodeA.split('-');
          if (!relationData.nodes[idA]) {
            relationData.nodes[idA] = {
              id: idA,
              name: nameA,
              category: this.getCategoryFromName(nameA)
            };
          }
          
          // 解析节点B信息
          const [nameB, idB] = nodeB.split('-');
          if (!relationData.nodes[idB]) {
            relationData.nodes[idB] = {
              id: idB,
              name: nameB,
              category: this.getCategoryFromName(nameB)
            };
          }
          
          // 添加连线
          relationData.links.push({
            source: idA,
            target: idB,
            relation: relation
          });
        }
      });
      
      // 转换为数组格式
      const graphData = {
        nodes: Object.values(relationData.nodes),
        links: relationData.links
      };
      
      // 处理节点类别
      this.processNodesCategories(graphData);
      
      // 处理并显示数据
      this.processGraphData(graphData);
      this.initGraph();
      this.isLoading = false;
    },
    
    // 根据节点名称推断类别
    getCategoryFromName(name) {
      const lowerName = name.toLowerCase();
      if (lowerName === '工业母机') return 0; // 核心
      if (lowerName === '上游' || lowerName.includes('原材料') || lowerName.includes('元器件')) return 1; // 上游
      if (lowerName === '中游') return 2; // 中游
      if (lowerName === '下游') return 3; // 下游
      
      // 默认类别根据父节点关系确定，先返回1
      return 1;
    },
    
    // 处理节点类别（根据连线关系）
    processNodesCategories(graphData) {
      const { nodes, links } = graphData;
      
      // 建立节点字典
      const nodeDict = {};
      nodes.forEach(node => {
        nodeDict[node.id] = node;
      });
      
      // 找到核心节点(工业母机)
      const coreNode = nodes.find(node => node.category === 0);
      if (!coreNode) return;
      
      // 构建邻接表
      const adjacencyList = {};
      links.forEach(link => {
        if (!adjacencyList[link.target]) {
          adjacencyList[link.target] = [];
        }
        adjacencyList[link.target].push(link.source);
      });
      
      // BFS遍历更新节点类别
      const queue = [coreNode.id];
      const visited = new Set();
      visited.add(coreNode.id);
      
      while (queue.length > 0) {
        const currentId = queue.shift();
        const currentNode = nodeDict[currentId];
        
        // 获取当前节点的所有子节点
        const childLinks = links.filter(link => link.source === currentId);
        
        childLinks.forEach(link => {
          const childId = link.target;
          const childNode = nodeDict[childId];
          
          if (childNode) {
            // 子节点类别 = 父节点类别 + 1，最大为3
            childNode.category = Math.min(currentNode.category + 1, 3);
            
            if (!visited.has(childId)) {
              visited.add(childId);
              queue.push(childId);
            }
          }
        });
      }
    },

    // 从后端获取图谱数据
    fetchGraphData() {
      this.isLoading = true
      // 这里替换为您的实际API调用
      // 使用axios或其他HTTP客户端
      this.$axios.get('/api/industry-chain')
        .then(response => {
          const data = response.data
          this.processGraphData(data)
          this.initGraph()
        })
        .catch(error => {
          console.error('获取产业链数据失败:', error)
          this.$message.error('获取产业链数据失败')
        })
        .finally(() => {
          this.isLoading = false
        })
    },

    // 处理后端返回的数据
    processGraphData(data) {
      // 处理节点数据
      this.graphData.nodes = data.nodes.map(node => {
        const colors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']
        const categoryLabels = ['核心', '上游', '中游', '下游']
        
        return {
          id: node.id,
          name: node.name,
          value: node.value || categoryLabels[node.category],
          category: node.category,
          itemStyle: {
            color: '#fff',
            borderColor: colors[node.category],
            borderWidth: 2,
            shadowColor: colors[node.category],
            shadowBlur: node.category === 0 ? 5 : 3
          },
          label: node.category === 0 ? {
            color: '#333',
            fontSize: 16,
            fontWeight: 'bold'
          } : undefined,
          x: node.x,
          y: node.y,
          description: node.description,
          dataSource: node.dataSource,
          icon: node.icon,
          properties: node.properties
        }
      })

      // 处理连线数据
      this.graphData.links = data.links.map(link => {
        // 查找目标节点的类别，用于设置连线颜色
        const targetNode = this.graphData.nodes.find(n => n.id === link.target)
        const category = targetNode ? targetNode.category : 0
        const colors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']
        
        return {
          source: link.source,
          target: link.target,
          lineStyle: {
            color: colors[category],
            width: 2,
            curveness: 0.1
          },
          value: link.value,
          relation: link.relation,
          description: link.description,
          properties: link.properties
        }
      })
    },

    initGraph() {
      this.$nextTick(() => {
        const graphDom = document.getElementById('graph')
        if (!graphDom) {
          console.error('图表容器未找到')
          return
        }
        
        if (this.graph) {
          this.graph.dispose()
        }
        
        this.graph = echarts.init(graphDom)
        
        const option = {
          title: {
            text: '产业链图谱',
            top: 'top',
            left: 'center',
            textStyle: {
              fontSize: 20,
              fontWeight: 'bold'
            }
          },
          tooltip: {
            show: true,
            formatter: function(params) {
              if (params.dataType === 'node') {
                return params.data.name + '<br/>' + params.data.value
              }
            }
          },
          series: [{
            type: 'graph',
            layout: 'none',
            data: this.graphData.nodes,
            links: this.graphData.links,
            roam: true,
            draggable: true,
            symbol: 'rect',
            symbolSize: [120, 40],
            categories: [
              { name: '核心' },
              { name: '上游' },
              { name: '中游' },
              { name: '下游' }
            ],
            label: {
              show: true,
              position: 'inside',
              formatter: '{b}',
              fontSize: 14,
              color: '#333'
            },
            edgeSymbol: ['none', 'none'],
            edgeLabel: {
              show: false
            },
            itemStyle: {
              borderWidth: 1,
              borderColor: '#ccc'
            },
            lineStyle: {
              color: '#ccc',
              width: 1,
              curveness: 0.1
            },
            emphasis: {
              scale: false,
              focus: 'adjacency',
              itemStyle: {
                borderColor: '#409EFF',
                borderWidth: 2
              }
            },
            force: {
              repulsion: 1500,
              edgeLength: [50, 200],
              layoutAnimation: false
            },
            selectedMode: 'single'
          }]
        }
        
        this.graph.setOption(option)
        this.addGraphEvents()
        this.updateLayout()
      })
    },

    // 更新节点布局
    updateLayout() {
      const option = this.graph.getOption()
      const nodes = option.series[0].data
      const links = option.series[0].links
      
      // 找到根节点
      const root = nodes.find(node => node.category === 0)
      if (!root) return

      // 设置根节点位置
      root.x = 400
      root.y = 300

      // 按层级对节点进行分组
      const levelNodes = [[], [], [], []]
      nodes.forEach(node => {
        if (node.category >= 0 && node.category < 4) {
          levelNodes[node.category].push(node)
        }
      })

      // 设置每层节点的位置
      const levelSpacing = 250 // 层级之间的水平间距
      const nodeSpacing = 100 // 同层节点之间的垂直间距
      
      levelNodes.forEach((nodesInLevel, level) => {
        if (level === 0) return // 跳过根节点
        
        const totalHeight = (nodesInLevel.length - 1) * nodeSpacing
        let startY = 300 - totalHeight / 2
        
        nodesInLevel.forEach((node, index) => {
          node.x = root.x + level * levelSpacing
          node.y = startY + index * nodeSpacing
        })
      })

      // 更新连线样式
      links.forEach(link => {
        // 支持通过id或name查找节点
        const findNode = (identifier) => {
          if (typeof identifier === 'object') {
            return identifier; // 如果已经是节点对象
          }
          
          // 先尝试通过id查找
          let node = nodes.find(n => n.id === identifier);
          // 如果没找到，再尝试通过name查找
          if (!node) {
            node = nodes.find(n => n.name === identifier);
          }
          return node;
        };
        
        const sourceNode = findNode(link.source);
        const targetNode = findNode(link.target);
        
        if (sourceNode && targetNode) {
          link.lineStyle = {
            color: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][targetNode.category],
            width: 2,
            curveness: 0.1
          }
        }
      })

      // 更新图表
      this.graph.setOption({
        series: [{
          data: nodes,
          links: links
        }]
      })
    },

    // 获取节点数据
    getNodes() {
      return [
        { 
          id: '1',
          name: '汽车产业',
          value: '产业核心',
          category: 0,
          itemStyle: {
            color: '#fff',
            borderColor: '#409EFF',
            borderWidth: 2,
            shadowColor: '#409EFF',
            shadowBlur: 5
          },
          label: {
            color: '#333',
            fontSize: 16,
            fontWeight: 'bold'
          }
        },
        { 
          id: '2',
          name: '原材料供应',
          value: '上游环节',
          category: 1,
          itemStyle: {
            color: '#fff',
            borderColor: '#67C23A',
            borderWidth: 2,
            shadowColor: '#67C23A',
            shadowBlur: 3
          }
        },
        {
          id: '3',
          name: '零部件供应',
          value: '上游环节',
          category: 1,
          itemStyle: {
            color: '#fff',
            borderColor: '#67C23A',
            borderWidth: 2,
            shadowColor: '#67C23A',
            shadowBlur: 3
          }
        },
        {
          id: '4',
          name: '整车制造',
          value: '中游环节',
          category: 2,
          itemStyle: {
            color: '#fff',
            borderColor: '#E6A23C',
            borderWidth: 2,
            shadowColor: '#E6A23C',
            shadowBlur: 3
          }
        },
        {
          id: '5',
          name: '销售渠道',
          value: '下游环节',
          category: 3,
          itemStyle: {
            color: '#fff',
            borderColor: '#F56C6C',
            borderWidth: 2,
            shadowColor: '#F56C6C',
            shadowBlur: 3
          }
        }
      ]
    },

    // 获取连线数据
    getLinks() {
      return [
        { 
          source: '汽车产业',
          target: '原材料供应',
          lineStyle: { color: '#67C23A' }
        },
        {
          source: '1',
          target: '3',
          lineStyle: { color: '#67C23A' }
        },
        {
          source: '2',
          target: '4',
          lineStyle: { color: '#E6A23C' }
        },
        {
          source: '3',
          target: '4',
          lineStyle: { color: '#E6A23C' }
        },
        {
          source: '4',
          target: '5',
          lineStyle: { color: '#F56C6C' }
        }
      ]
    },

    // 添加图表事件监听
    addGraphEvents() {
      if (!this.graph) return

      // 添加点击事件处理
      this.graph.on('click', this.handleNodeClick)
      
      // 添加右键点击事件处理
      this.graph.on('contextmenu', this.handleContextMenu)

      // 拖拽节点相关变量
      let isDragging = false
      let draggedNode = null
      let dragStartPosition = null
      let dragTargetNode = null

      // 开始拖拽
      this.graph.on('mousedown', params => {
        // 点击时隐藏上下文菜单
        this.showContextMenu = false
        
        if (params.dataType === 'node' && this.isEditMode) {
          isDragging = true
          draggedNode = params.data
          dragStartPosition = {
            x: draggedNode.x,
            y: draggedNode.y
          }
          
          // 选中当前节点
          this.selectedNode = draggedNode
          this.updateNodeSelection(draggedNode.name)
        }
      })

      // 拖拽过程中
      this.graph.on('mousemove', params => {
        if (!isDragging || !draggedNode || !this.isEditMode) return

        const option = this.graph.getOption()
        const nodes = option.series[0].data
        
        // 计算鼠标位置相对于图表容器的坐标
        const point = this.graph.convertFromPixel({seriesIndex: 0}, [
          params.event.offsetX,
          params.event.offsetY
        ])
        
        // 更新被拖拽节点的位置
        draggedNode.x = point[0]
        draggedNode.y = point[1]

        // 检测是否有可连接的目标节点
        dragTargetNode = null
        for (const node of nodes) {
          if (node.name !== draggedNode.name) {
            const dx = node.x - draggedNode.x
            const dy = node.y - draggedNode.y
            const distance = Math.sqrt(dx * dx + dy * dy)
            
            if (distance < 150) {
              dragTargetNode = node
              node.itemStyle = {
                ...node.itemStyle,
                borderWidth: 3,
                borderColor: '#409EFF',
                shadowBlur: 10
              }
            } else {
              node.itemStyle = {
                ...node.itemStyle,
                borderWidth: node.name === this.selectedNode?.name ? 3 : 2,
                borderColor: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][node.category],
                shadowBlur: 3
              }
            }
          }
        }

        this.graph.setOption(option)
      })

      // 拖拽结束
      this.graph.on('mouseup', params => {
        if (!isDragging || !draggedNode || !this.isEditMode) return

        const option = this.graph.getOption()
        const nodes = option.series[0].data
        const links = option.series[0].links

        // 如果有目标节点，创建新连线
        if (dragTargetNode) {
          // 使用ID优先，如果没有ID则使用名称
          const sourceId = draggedNode.id || draggedNode.name;
          const targetId = dragTargetNode.id || dragTargetNode.name;
          
          // 检查连线是否已存在
          const existingLink = links.find(link => 
            (link.source === sourceId && link.target === targetId) ||
            (link.source === targetId && link.target === sourceId) ||
            (typeof link.source === 'object' && typeof link.target === 'object' &&
             ((link.source.id === sourceId && link.target.id === targetId) ||
              (link.source.id === targetId && link.target.id === sourceId)))
          )

          if (!existingLink) {
            // 添加新连线
            links.push({
              source: sourceId,
              target: targetId,
              lineStyle: {
                color: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][draggedNode.category],
                width: 2,
                curveness: 0.1
              }
            })

            // 更新节点关系和类别
            this.updateNodeRelationships(draggedNode, dragTargetNode, nodes, links)

            this.$message.success('成功创建连线')
          }
        }

        // 重置所有节点样式
        nodes.forEach(node => {
          node.itemStyle = {
            ...node.itemStyle,
            borderWidth: node.name === this.selectedNode?.name ? 3 : 2,
            borderColor: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][node.category],
            shadowBlur: 3,
            shadowColor: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][node.category]
          }
        })

        isDragging = false
        draggedNode = null
        dragStartPosition = null
        dragTargetNode = null
        
        // 更新图表
        this.graph.setOption(option)
      })

      // 监听节点点击事件
      this.graph.on('click', (params) => {
        if (params.dataType === 'node') {
          // 更新侧边栏数据
          const nodeData = {
            topic: {
              title: params.data.name,
              type: 'industry',
              articleCount: 0
            },
            articles: []
          }
          this.$root.$emit('update-sidebar', nodeData)
        }
      })

      // 监听窗口大小变化
      window.addEventListener('resize', () => {
        this.graph && this.graph.resize()
      })
      
      // 点击空白处隐藏菜单
      document.addEventListener('click', () => {
        this.showContextMenu = false
      })
    },

    // 处理右键菜单
    handleContextMenu(params) {
      // 如果不是节点或不在编辑模式下，不显示菜单
      if (params.dataType !== 'node' || !this.isEditMode) {
        this.showContextMenu = false
        return
      }
      
      // 阻止默认右键菜单
      params.event.event.preventDefault()
      
      // 选中当前节点
      this.selectedNode = params.data
      this.updateNodeSelection(params.data.name)
      
      // 显示自定义菜单
      this.showContextMenu = true
      this.contextMenuStyle = {
        left: params.event.event.offsetX + 'px',
        top: params.event.event.offsetY + 'px'
      }
    },
    
    // 从右键菜单添加节点
    addNodeFromMenu() {
      this.showContextMenu = false
      
      if (!this.isEditMode || !this.selectedNode) return

      this.$prompt('请输入节点名称', '添加子节点', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputPlaceholder: '节点名称'
      }).then(({ value }) => {
        if (!value) return

        // 新节点类别为选中节点的下一级
        const newCategory = Math.min(this.selectedNode.category + 1, 3)
        const colors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']
        
        const option = this.graph.getOption()
        const nodes = option.series[0].data
        const links = option.series[0].links

        // 生成唯一ID
        const newId = 'n' + Date.now().toString();
        
        // 创建新节点
        const newNode = {
          id: newId,
          name: value,
          value: ['核心', '上游', '中游', '下游'][newCategory],
          category: newCategory,
          x: this.selectedNode.x + 250,
          y: this.selectedNode.y,
          itemStyle: {
            color: '#fff',
            borderColor: colors[newCategory],
            borderWidth: 2,
            shadowBlur: 3,
            shadowColor: colors[newCategory]
          }
        }

        // 添加节点和连线
        nodes.push(newNode)
        links.push({
          source: this.selectedNode.id || this.selectedNode.name,
          target: newId,
          lineStyle: {
            color: colors[newCategory],
            width: 2,
            curveness: 0.1
          }
        })

        // 更新图谱
        this.graph.setOption({
          series: [{
            data: nodes,
            links: links
          }]
        })

        // 更新布局
        this.updateLayout()
        
        this.$message.success('节点添加成功')
      }).catch(() => {})
    },
    
    // 从右键菜单编辑节点
    editNodeFromMenu() {
      this.showContextMenu = false
      
      if (!this.isEditMode || !this.selectedNode) return
      
      this.$prompt('编辑节点名称', '编辑节点', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputValue: this.selectedNode.name
      }).then(({ value }) => {
        if (!value || value === this.selectedNode.name) return
        
        const option = this.graph.getOption()
        const nodes = option.series[0].data
        const links = option.series[0].links
        
        // 更新节点名称
        const node = nodes.find(n => n.name === this.selectedNode.name)
        if (node) {
          const oldName = node.name
          node.name = value
          
          // 如果连线使用的是名称而非ID，更新连线
          if (!node.id) {
            links.forEach(link => {
              if (typeof link.source !== 'object' && link.source === oldName) link.source = value
              if (typeof link.target !== 'object' && link.target === oldName) link.target = value
            })
          }
          
          this.graph.setOption(option)
          this.selectedNode = node
          this.$message.success('节点名称已更新')
        }
      }).catch(() => {})
    },

    // 检查是否会形成循环依赖
    wouldCreateCycle(sourceNode, targetNode, links) {
      const visited = new Set()
      
      const dfs = (current) => {
        if (current === sourceNode) return true
        if (visited.has(current)) return false
        
        visited.add(current)
        const children = links.filter(link => link.source === current).map(link => link.target)
        
        return children.some(child => dfs(child))
      }
      
      return dfs(targetNode)
    },

    // 开关编辑模式
    toggleEditMode() {
      this.isEditMode = !this.isEditMode
      if (this.isEditMode) {
        this.$message({
          message: '已进入编辑模式，可拖拽节点、右键操作、拖动创建连线',
          type: 'success'
        })
      } else {
        this.$message({
          message: '已退出编辑模式',
          type: 'info'
        })
        this.selectedNode = null
        this.updateNodeSelection(null)
        this.showContextMenu = false
      }
    },

    // 保存图谱
    saveGraph() {
      // 准备要保存的数据
      const option = this.graph.getOption()
      const nodes = option.series[0].data
      const links = option.series[0].links
      
      // 将数据转换为后端需要的格式
      const saveData = {
        nodes: nodes.map(node => ({
          id: node.id || node.name,
          name: node.name,
          value: node.value,
          category: node.category,
          x: node.x,
          y: node.y,
          description: node.description,
          dataSource: node.dataSource,
          icon: node.icon,
          properties: node.properties
        })),
        links: links.map(link => ({
          source: typeof link.source === 'object' ? link.source.id || link.source.name : link.source,
          target: typeof link.target === 'object' ? link.target.id || link.target.name : link.target,
          value: link.value,
          relation: link.relation,
          description: link.description,
          properties: link.properties
        }))
      }
      
      // 发送到后端保存
      // 这里替换为您的实际API调用
      this.$axios.post('/api/industry-chain', saveData)
        .then(() => {
          this.$message.success('图谱保存成功')
        })
        .catch(error => {
          console.error('保存失败:', error)
          this.$message.error('图谱保存失败')
        })
    },

    // 更新节点选中状态
    updateNodeSelection(selectedNodeName) {
      const option = this.graph.getOption()
      const nodes = option.series[0].data
      
      nodes.forEach(node => {
        node.itemStyle = {
          ...node.itemStyle,
          borderWidth: node.name === selectedNodeName ? 3 : 2
        }
      })
      
      this.graph.setOption(option)
    },

    // 添加新节点
    addNode() {
      if (!this.isEditMode) return

      this.$prompt('请输入节点名称', '添加节点', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputPlaceholder: '节点名称'
      }).then(({ value }) => {
        if (!value) return

        // 决定新节点类别
        let newCategory = 1 // 默认为上游
        if (this.selectedNode) {
          // 如果有选中节点，则新节点类别为选中节点的下一级
          newCategory = Math.min(this.selectedNode.category + 1, 3)
        }

        const colors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']
        const option = this.graph.getOption()
        const nodes = option.series[0].data
        const links = option.series[0].links

        // 生成唯一ID
        const newId = 'n' + Date.now().toString();
        
        // 创建新节点
        const newNode = {
          id: newId,
          name: value,
          value: ['核心', '上游', '中游', '下游'][newCategory],
          category: newCategory,
          x: this.selectedNode ? this.selectedNode.x + 250 : 400,
          y: this.selectedNode ? this.selectedNode.y : 300 + nodes.length * 50,
          itemStyle: {
            color: '#fff',
            borderColor: colors[newCategory],
            borderWidth: 2,
            shadowBlur: 3,
            shadowColor: colors[newCategory]
          }
        }

        // 添加节点
        nodes.push(newNode)

        // 如果有选中节点，添加连线
        if (this.selectedNode) {
          links.push({
            source: this.selectedNode.id || this.selectedNode.name,
            target: newId,
            lineStyle: {
              color: colors[newCategory],
              width: 2,
              curveness: 0.1
            }
          })
        }

        // 更新图谱
        this.graph.setOption({
          series: [{
            data: nodes,
            links: links
          }]
        })

        // 更新布局
        this.updateLayout()

        this.$message.success('节点添加成功')
      }).catch(() => {})
    },

    // 删除选中节点
    deleteSelectedNode() {
      this.showContextMenu = false
      
      if (!this.isEditMode || !this.selectedNode) return

      this.$confirm(`确认删除节点 "${this.selectedNode.name}"?`, '删除节点', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const option = this.graph.getOption()
        const nodes = option.series[0].data
        const links = option.series[0].links

        // 获取要删除的节点ID或名称
        const nodeId = this.selectedNode.id || this.selectedNode.name;
        
        // 获取要删除的节点名称列表(包括子节点)
        const nodesToDelete = this.getNodeTreeToDelete(nodeId, nodes, links)
        
        // 删除节点及其所有子节点
        const filteredNodes = nodes.filter(node => {
          const id = node.id || node.name;
          return !nodesToDelete.includes(id);
        })
        
        // 删除与所有这些节点相关的连线
        const filteredLinks = links.filter(link => {
          const sourceId = typeof link.source === 'object' ? (link.source.id || link.source.name) : link.source;
          const targetId = typeof link.target === 'object' ? (link.target.id || link.target.name) : link.target;
          return !nodesToDelete.includes(sourceId) && !nodesToDelete.includes(targetId);
        })

        // 更新图谱
        this.graph.setOption({
          series: [{
            data: filteredNodes,
            links: filteredLinks
          }]
        })

        this.selectedNode = null;
        
        // 提示用户删除结果
        if (nodesToDelete.length > 1) {
          this.$message.success(`已删除节点"${this.selectedNode.name}"及其${nodesToDelete.length - 1}个子节点`)
        } else {
          this.$message.success('节点删除成功')
        }
      }).catch(() => {})
    },
    
    // 获取需要删除的节点树(包括子节点)
    getNodeTreeToDelete(nodeIdentifier, nodes, links) {
      const result = [nodeIdentifier]
      
      // 查找当前节点的所有子节点
      const childLinks = links.filter(link => {
        const sourceId = typeof link.source === 'object' ? (link.source.id || link.source.name) : link.source;
        return sourceId === nodeIdentifier;
      })
      
      // 递归获取每个子节点及其子节点
      childLinks.forEach(link => {
        const childNodeId = typeof link.target === 'object' ? (link.target.id || link.target.name) : link.target;
        const childTree = this.getNodeTreeToDelete(childNodeId, nodes, links)
        result.push(...childTree)
      })
      
      return [...new Set(result)] // 去重
    },
    
    // 添加更新节点关系和类别的方法
    updateNodeRelationships(sourceNode, targetNode, nodes, links) {
      const colors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']
      
      // 根据节点的类别决定父子关系
      let parentNode, childNode
      
      if (sourceNode.category <= targetNode.category) {
        parentNode = sourceNode
        childNode = targetNode
      } else {
        parentNode = targetNode
        childNode = sourceNode
      }
      
      // 获取节点标识符
      const parentId = parentNode.id || parentNode.name;
      const childId = childNode.id || childNode.name;
      
      // 查找子节点的当前父节点连线(不包括刚刚创建的新连线)
      const currentParentLinks = links.filter((link, index) => {
        // 过滤掉最后一个(刚添加的)连线
        if (index >= links.length - 1) return false;
        
        const targetId = typeof link.target === 'object' ? (link.target.id || link.target.name) : link.target;
        const sourceId = typeof link.source === 'object' ? (link.source.id || link.source.name) : link.source;
        
        // 目标是当前子节点，且源节点类别比子节点小(即符合产业链层级)
        if (targetId === childId) {
          const sourceNode = nodes.find(n => (n.id || n.name) === sourceId);
          return sourceNode && sourceNode.category < childNode.category;
        }
        return false;
      });
      
      // 如果有多个父节点连线，保留新添加的，删除旧的
      if (currentParentLinks.length > 0) {
        // 移除旧的父节点连线
        for (let i = links.length - 2; i >= 0; i--) {
          const link = links[i];
          const targetId = typeof link.target === 'object' ? (link.target.id || link.target.name) : link.target;
          
          if (targetId === childId) {
            const sourceId = typeof link.source === 'object' ? (link.source.id || link.source.name) : link.source;
            const sourceNode = nodes.find(n => (n.id || n.name) === sourceId);
            
            if (sourceNode && sourceNode.category < childNode.category) {
              links.splice(i, 1);
            }
          }
        }
        
        // 提示用户
        this.$message.warning('已更新节点关系，移除了旧的父级连线')
      }
      
      // 更新子节点的类别
      const newCategory = Math.min(parentNode.category + 1, 3)
      if (childNode.category !== newCategory) {
        childNode.category = newCategory
        childNode.value = ['核心', '上游', '中游', '下游'][newCategory]
        childNode.itemStyle = {
          ...childNode.itemStyle,
          borderColor: colors[newCategory],
          shadowColor: colors[newCategory]
        }
        
        // 更新最新添加的连线样式
        const newLink = links[links.length - 1]
        newLink.lineStyle = {
          color: colors[newCategory],
          width: 2,
          curveness: 0.1
        }
        
        // 递归更新所有子节点的类别
        this.updateChildrenCategories(childId, newCategory, nodes, links)
      }
    },
    
    // 递归更新子节点类别
    updateChildrenCategories(parentIdentifier, parentCategory, nodes, links) {
      const colors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']
      
      const childLinks = links.filter(link => {
        const sourceId = typeof link.source === 'object' ? (link.source.id || link.source.name) : link.source;
        return sourceId === parentIdentifier;
      });
      
      childLinks.forEach(link => {
        const childId = typeof link.target === 'object' ? (link.target.id || link.target.name) : link.target;
        const childNode = nodes.find(n => (n.id || n.name) === childId);
        
        if (childNode) {
          const newCategory = Math.min(parentCategory + 1, 3)
          if (childNode.category !== newCategory) {
            childNode.category = newCategory
            childNode.value = ['核心', '上游', '中游', '下游'][newCategory]
            childNode.itemStyle = {
              ...childNode.itemStyle,
              borderColor: colors[newCategory],
              shadowColor: colors[newCategory]
            }
            link.lineStyle = {
              color: colors[newCategory],
              width: 2,
              curveness: 0.1
            }
            
            // 继续递归更新此节点的子节点
            this.updateChildrenCategories(childId, newCategory, nodes, links)
          }
        }
      });
    },

    // 点击事件处理
    handleNodeClick(params) {
      // 点击时隐藏上下文菜单
      this.showContextMenu = false
      
      if (params.dataType === 'node') {
        // 更新选中的节点
        this.selectedNode = params.data
        this.updateNodeSelection(params.data.name)
        
        // 编辑模式下允许编辑节点名称
        if (this.isEditMode) {
          this.$prompt('编辑节点名称', '编辑节点', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            inputValue: params.data.name
          }).then(({ value }) => {
            if (!value || value === params.data.name) return
            
            const option = this.graph.getOption()
            const nodes = option.series[0].data
            const links = option.series[0].links
            
            // 更新节点名称
            const node = nodes.find(n => n.name === params.data.name)
            if (node) {
              const oldName = node.name
              node.name = value
              
              // 更新连线
              links.forEach(link => {
                if (link.source === oldName) link.source = value
                if (link.target === oldName) link.target = value
              })
              
              this.graph.setOption(option)
              this.selectedNode = node
              this.$message.success('节点名称已更新')
            }
          }).catch(() => {})
        }
      }
    },

    // 处理关系数据导入
    handleImportRelation() {
      if (!this.relationData.trim()) {
        this.$message.warning('请输入关系数据');
        return;
      }
      
      // 解析关系数据
      this.parseRelationData(this.relationData);
      this.showRelationDialog = false;
      this.$message.success('关系数据导入成功');
    },

    // 处理图谱数据更新
    handleGraphDataUpdate(data) {
      if (!data || !data.nodes || !data.links) return;
      
      // 更新图谱数据
      this.graphData = {
        nodes: data.nodes.map(node => ({
          ...node,
          symbolSize: node.category === 0 ? 60 : 50,
          itemStyle: {
            color: '#fff',
            borderColor: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][node.category],
            borderWidth: 2,
            shadowColor: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][node.category],
            shadowBlur: node.category === 0 ? 5 : 3
          },
          label: {
            show: true,
            position: 'inside',
            formatter: '{b}',
            fontSize: node.category === 0 ? 16 : 14,
            color: '#333',
            fontWeight: node.category === 0 ? 'bold' : 'normal'
          }
        })),
        links: data.links.map(link => ({
          ...link,
          lineStyle: {
            color: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C'][this.getLinkCategory(link, data.nodes)],
            width: 2,
            curveness: 0.1
          }
        }))
      };
      
      // 重新初始化图表
      this.initGraph();
      
      // 更新布局
      this.$nextTick(() => {
        this.updateLayout();
      });
    },
    
    // 获取连线的类别（根据目标节点的类别）
    getLinkCategory(link, nodes) {
      const targetNode = nodes.find(node => node.id === link.target);
      return targetNode ? targetNode.category : 0;
    },
  },
  mounted() {
    // 监听产业链数据更新事件
    this.$root.$on('update-industry-chain', this.handleGraphDataUpdate);
    
    // 使用本地JSON数据
    this.loadLocalData();
    
    // 监听窗口大小变化，调整图谱大小
    window.addEventListener('resize', () => {
      if (this.graph) {
        this.graph.resize();
      }
    });
  }
}
</script>

<style lang="less" scoped>
.graph-container {
  height: 600px;
  display: flex;
  flex-direction: column;
  
  .graph-tools {
    margin-bottom: 16px;
    padding: 12px;
    background-color: #f8f9fa;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    
    .el-button-group {
      .el-button {
        padding: 8px 16px;
        border-radius: 6px;
        font-weight: 500;
        
        &:hover {
          transform: translateY(-1px);
        }
      }
    }

    .tool-tips {
      display: flex;
      gap: 8px;
      
      .el-tag {
        padding: 4px 8px;
        font-size: 12px;
      }
    }
  }
  
  .graph-content {
    flex: 1;
    border: 1px solid #e4e7ed;
    border-radius: 8px;
    background-color: white;
    box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05);
    position: relative;
    
    #graph {
      width: 100%;
      height: 100%;
    }
    
    .context-menu {
      position: absolute;
      background-color: white;
      border-radius: 4px;
      box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
      z-index: 100;
      
      ul {
        list-style: none;
        padding: 0;
        margin: 0;
        
        li {
          padding: 8px 16px;
          cursor: pointer;
          font-size: 14px;
          transition: all 0.3s;
          
          i {
            margin-right: 5px;
          }
          
          &:hover {
            background-color: #f5f7fa;
            color: #409EFF;
          }
          
          &:first-child {
            border-radius: 4px 4px 0 0;
          }
          
          &:last-child {
            border-radius: 0 0 4px 4px;
          }
        }
      }
    }
  }
  
  .format-tip {
    background-color: #f8f9fa;
    padding: 10px;
    border-radius: 4px;
    color: #666;
    font-size: 14px;
    line-height: 1.5;
    margin-bottom: 10px;
  }
}
</style> 